package com.xneure.database.sql;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;
import com.xneure.database.DynamicDataSource;
import com.xneure.database.annotation.DBField;
import com.xneure.database.annotation.DataType;
import com.xneure.database.dialect.SqlDialect;
import com.xneure.database.metaobject.FieldMetaObject;
import com.xneure.utils.DateUtil;
import com.xneure.utils.JsonUtil;
import com.xneure.utils.ObjectUtil;
import com.xneure.utils.bean.GUID;

public class ValueConvert{
	public Object sqlValue(FieldMetaObject fieldMetaObject,Object _value){
		if(null == _value){
			return null;
		}
		DBField annotation = (DBField)fieldMetaObject.getAnnotation();
		if(annotation != null && annotation.dataType() == DataType.JSON){
			return "'".concat(escapeSql(JsonUtil.toJson(_value))).concat("'");
		}else{
			return sqlValue(_value);
		}
	}

	@SuppressWarnings("rawtypes")
	public Object sqlValue(Object _value){
		if(ObjectUtil.isSubclass(_value,Number.class) == false){
			if(_value instanceof Boolean){
				return (boolean)_value ? 1 : 0;
			}else if(_value instanceof Date){
				SqlDialect sqlDialect = getSqlDialect();
				if(null != sqlDialect){
					return sqlDialect.toDate(_value);
				}
				return "'".concat(DateUtil.dateFormat((Date)_value)).concat("'");
			}else if(_value instanceof Timestamp){
				SqlDialect sqlDialect = getSqlDialect();
				if(null != sqlDialect){
					return sqlDialect.toTimestamp(_value);
				}
				return "'".concat(DateUtil.dateFormat((Date)_value,DateUtil.DEFAULT_TIMESTAMP_FORMAT)).concat("'");
			}else if(Enum.class.isAssignableFrom(_value.getClass())){
				_value = ((Enum)_value).name();
			}
			return "'".concat(escapeSql(_value.toString())).concat("'");
		}else{
			return _value;
		}
	}

	protected SqlDialect getSqlDialect(){
		return DynamicDataSource.getSqlDialect();
	}

	public String escapeSql(String value){
		if(ObjectUtil.isNotNull(value)){
			value = value.replace("'","''");
		}
		return value;
	}

	public Object getRandomValue(Class<?> cls){
		if(GUID.class.equals(cls)){
			return GUID.randomID();
		}else if(Long.class.equals(cls)){
			return GUID.randomLong();
		}else if(Date.class.equals(cls) || java.sql.Date.class.equals(cls)){
			return new Date(System.currentTimeMillis());
		}else{
			return null;
		}
	}

	public Object objectValue(Field field,Object _value){
		if(null != _value){
			if(_value instanceof Clob){
				try{
					Clob _val = (Clob)_value;
					if(String.class.isAssignableFrom(field.getType())){
						return _val.getSubString(1,(int)_val.length());
					}else if(InputStream.class.isAssignableFrom(field.getType())){
						return _val.getAsciiStream();
					}else if(byte[].class.isAssignableFrom(field.getType())){
						byte[] data = null;
						try(InputStream is = _val.getAsciiStream();){
							if(is.available() == 0){
								return data;
							}
							data = new byte[is.available()];
							is.read(data);
							is.close();
							return data;
						}catch(IOException e){
							return data;
						}
					}else{
						return null;
					}
				}catch(SQLException e){
					return null;
				}
			}
			if(_value instanceof Blob){
				try{
					Blob _val = (Blob)_value;
					if(String.class.isAssignableFrom(field.getType())){
						return new String(_val.getBytes(1,(int)_val.length()));
					}else if(InputStream.class.isAssignableFrom(field.getType())){
						return _val.getBinaryStream();
					}else if(byte[].class.isAssignableFrom(field.getType())){
						return _val.getBytes(0,(int)_val.length());
					}else{
						return null;
					}
				}catch(SQLException e){
					return null;
				}
			}
			_value = ObjectUtil.convertValue(_value,field.getType());
		}
		return _value;
	}
}
